﻿using MathExp.Errors;
using System;
using System.Collections;
using System.Diagnostics;

namespace MathExp
{
    public abstract class Converter
    {
        public abstract int precedenceCompare(Operator op1, Operator op2);

        public Object[] convert(Object[] infixExpr)
        {
            return convert(infixExpr, 0, infixExpr.Length);
        }
        public Object[] convert(Object[] infixExpr, int offset, int len)
        {
            if (infixExpr.Length - offset < len)
                throw new IllegalArgumentException();
            // 创建一个输出表达式，用来存放结果
            ArrayList output = new ArrayList();
            // 创建一个工作栈
            Stack stack = new Stack();
            int currInputPosition = offset;  // 当前位置（于输入队列）
            //  System.out.println(" ----------- Begin conversion procedure --------------");
            while (currInputPosition < offset + len)
            {
                Object currInputElement = infixExpr[currInputPosition++];
                if (currInputElement is Decimal) // 数值元素直接输出
                {
                    output.Add(currInputElement);
                    Debug.WriteLine("NUMBER:"+currInputElement);//TEMP! 
                }
                else if (currInputElement is Bracket) // 遇到括号，进栈或进行匹配
                {
                    Bracket currInputBracket = (Bracket)currInputElement;
                    if (currInputBracket.ToString() == Bracket.LEFT_BRACKET.ToString())
                    { // 左括号进栈
                        stack.Push(currInputElement);
                    }
                    else
                    { // 右括号，寻求匹配（左括号）
                        // 弹出所有的栈元素 ( 运算符 ) 直到遇到 ( 左 ) 括号
                        Object stackElement;
                        do
                        {
                            if (stack.Count > 0)
                                stackElement = stack.Pop();
                            else
                                throw new IllegalExpressionException("bracket(s) mismatch");
                            if (stackElement is Bracket)
                                break;
                            output.Add(stackElement);
                            Debug.WriteLine("OPERATOR POPUP:" + stackElement);//TEMP!
                        } while (true);
                    }
                }
                else if (currInputElement is Operator)
                {
                    Operator currInputOperator = (Operator)currInputElement;
                    // 弹出所有优先级别高于或等于当前的所有运算符
                    // ( 直到把满足条件的全部弹出或者遇到左括号 ) 
                    while (stack.Count > 0)
                    {
                        Object stackElement = stack.Peek();
                        if (stackElement is Bracket)
                        {
                            break;// 这一定是左括号，没有可以弹出的了
                        }
                        else
                        {
                            Operator stackOperator = (Operator)stackElement;
                            if (precedenceCompare(stackOperator, currInputOperator) >= 0)
                            {
                                // 优先级高于等于当前的，弹出（至输出队列）
                                stack.Pop();
                                output.Add(stackElement);
                                Debug.WriteLine("OPERATOR:" + stackElement);//TEMP! 
                            }
                            else
                            {    // 优先级别低于当前的，没有可以弹出的了
                                break;
                            }
                        }
                    }
                    // 当前运算符进栈
                    stack.Push(currInputElement);
                }
                else //if (currInputElement instanceof Variable) 
                // 其它一律被认为变量，变量也直接输出
                {
                    output.Add(currInputElement);
                    Debug.WriteLine("VARIABLE:" + currInputElement);//TEMP! 
                }
            }
            // 将栈中剩下的元素 ( 运算符 ) 弹出至输出队列
            while (stack.Count > 0)
            {
                Object stackElement = stack.Pop();
                output.Add(stackElement);
                Debug.WriteLine("LEFT STACK OPERATOR:" + stackElement);//TEMP! 
            }
            Debug.WriteLine("------------ End conversion procedure --------------");
            return output.ToArray();
        }
    }
    public class MathConverter:Converter{
        public override int precedenceCompare(Operator op1, Operator op2)
        {
            if (op1.PRI > op2.PRI)
            {
                return 1;
            }
            else if (op1.PRI < op2.PRI)
            {
                return -1;
            }else{
                return 0;
            }
        }
    }
}
